import CanvasUtils from '@/utils/CanvasUtils';

export default class Visual {

	public Canvas: CanvasUtils;

	public constructor(el: HTMLCanvasElement) {
		this.Canvas = new CanvasUtils(el);
	}

	public async Load(): Promise<void> {
		this.DrawAll();
	}

	rect: any;
	list: any;
	oneX: any;
	getX: any;
	getY: any;
	maxH: any;
	saveList: any[] = [];

	private DrawAll() {
		const canvas = this.Canvas;
		canvas.Clear();
		const rect = this.rect = { x: 10, y: 10, w: 400, h: 800 };
		const list = this.list = [5, 5, 7, 15, 15, 16, 17, 20, 20, 30, 33, 50, 45, 45, 47, 31, 31, 11];
		const oneX = this.oneX = rect.w / (list.length);
		const maxH = this.maxH = rect.h / Math.max(...list);
		const getX = this.getX = (i: number) => oneX * i;
		const getY = this.getY = (i: number) => rect.h - list[i] * maxH;
		canvas.Save();
		canvas.Translate(rect.x, rect.y)
		this.DrawLine();
		this.DrawBody();
		this.DrawPoint();
		canvas.Restore();
	}

	private DrawLine() {
		const canvas = this.Canvas;
		const { rect, maxH } = this;
		if (true) {
			canvas.BeginPath();
			for (let i = 0; i < 20; i++) {
				const y = i * 5 * maxH;
				canvas.MoveTo({ X: 0, Y: rect.h - y });
				canvas.LineTo({ X: 400, Y: rect.h - y });
				canvas.FillText({
					Spot: { X: 0, Y: rect.h - y },
					Text: (i * 5).toFixed()
				});
			}
		}
		canvas.Stroke();
	}
	private DrawBody() {
		const canvas = this.Canvas;
		const { rect, list, getX, getY } = this;
		const saveList: any[] = this.saveList = [];
		const length = list.length;
		canvas.BeginPath();
		for (let i = 0; i < length; i++) {
			const last2X = getX(i - 2);
			const last2Y = getY(i - 2);
			const last1X = getX(i - 1);
			const last1Y = getY(i - 1);
			const nowX = getX(i);
			const nowY = getY(i);
			const nextX = getX(i + 1);
			const nextY = getY(i + 1);
			let cAx = last1X + (nowX - last2X) * .1;
			let cAy = last1Y + (nowY - last2Y) * .1;
			let cBx = nowX - (nextX - last1X) * .1;
			let cBy = nowY - (nextY - last1Y) * .1;
			if (i === 0) {
				canvas.Ctx.moveTo(nowX, nowY)
				continue;
			}
			else if (i === 1) {
				cAx = last1X + (nowX - 0) * .1
				cAy = last1Y + (nowY - rect.h) * .1
			}
			else if (i === list.length - 1) {
				cBx = nowX - (nowX - last1X) * .1
				cBy = nowY - (nowY - last1Y) * .1
			}
			if (nowY === last1Y) {
				cAy = nowY;
				cBy = nowY;
			}
			if (last1Y === last2Y) {
				cAx = last1X + (nowX - last2X) * .3;
				cAy = last1Y;
			}
			if (nowY === nextY) {
				cBx = nowX - (nextX - last1X) * .3;
				cBy = nowY;
			}
			saveList.push([
				{ X: cAx, Y: cAy },
				{ X: cBx, Y: cBy },
			]);
			canvas.Ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY);
		}
		canvas.Stroke();
	}

	private DrawPoint() {
		const canvas = this.Canvas;
		const { rect, list, getX, getY, saveList } = this;
		saveList.forEach(([pA, pB]) => {
			canvas.BeginPath();
			canvas.StrokeStyle = "red";
			canvas.Arc({
				Spot: pA,
				Radius: 5,
				StartAngle: { Value: 0 },
				EndAngle: { Value: Math.PI * 2 },
			});
			canvas.Stroke();
			canvas.BeginPath();
			canvas.StrokeStyle = "blue";
			canvas.Arc({
				Spot: pB,
				Radius: 5,
				StartAngle: { Value: 0 },
				EndAngle: { Value: Math.PI * 2 },
			});
			canvas.Stroke();
		});
	}

}
